$(function(){
	/** 地雷地图的二维数组 */
	let grid;
	
	/** 地图区块常量：没有地雷格子 */
	const CELL_EMPTY = 0;
	/** 地图区块常量：有地雷的格子 */
	const CELL_MINE  = 1;
	/** 地图区块常量：已扫除地雷的格子 */
	const CELL_CLEAR = 2;
	
	/** 游戏状态常量：正在游戏 */
	const GAME_ON = 1;
	/** 游戏状态常量：游戏结束 */
	const GAME_OFF = 0;
	/** 游戏的实时状态 */
	let gameStatus = 1;

	let gamePage   = $('#gamePage');
	let statusBtn  = $('#statusBtn');
	let mineMap    = $('#mineMap');
	let levelRadio = gamePage.find('input[name=radio]');
	let helpSwitch = $('#helperSwitch');
	let lineHelper = $('#helpLineSwitch');

	let startTime  = 0;
	let timeLabel  = $('.game-statistics label:eq(0)');
	let countLabel = $('.game-statistics label:eq(1)');

	let mineCount;
	let mineCountSign;
	let mineSize     = { x : 9 , y : 9 };	// 地图的尺寸
	let mineCountObj = $('#mineCount');	// 显示地雷总数的DIV
	
	
	/**
	 *	9x9		16x16		16x30
	 * @param obj {HTMLElement}	普通的单选框，选择游戏难度的dom对象
	 */
	// obj 是选中的游戏等级的单选按钮的 dom 对象
	function createMap(obj){
		if(!obj && !obj.checked){
			return;
		}
		statusBtn.attr('src','image/smile.png');
		mineCount = parseInt(obj.value);
		mineCountObj.text(mineCount);
		mineCountSign = mineCount;
		if(obj.id==='level1'){
			mineSize = {x:9, y:9};
		} else if(obj.id==='level2'){
			mineSize = {x:16, y:16};
		} else if(obj.id==='level3'){
			mineSize = {x:16, y:30};
		}
		mineSize.count = mineSize.x * mineSize.y;
		grid = new Array(mineSize.x);
		let content = '<table cellspacing="0">';
		for(let i=0; i<mineSize.x; i++){
			content += '<tr>';
			grid[i] = new Array(mineSize.y);
			for(let j=0; j<mineSize.y; j++){
				grid[i][j] = CELL_EMPTY;
				content += '<td id="box_' + i + '_' + j + '" data-x="' + i + '" data-y="' + j + '" ></td>';
			}
			content += '</tr>';
		}
		content += '</table>';

		let mineTable = $(content);
		mineTable.find('td[id^=box_]').mousedown(mouseRightClick);
		mineMap.html('');
		mineMap.html(mineTable);

		randomMine();
		gameStatus = GAME_ON;
		timeCounting();
	}
	
	// 右键点击格子(取消)标记地雷
	function mouseRightClick(event){
		let target = $(this);
		if(gameStatus===GAME_OFF || event.button!==2){
			return;
		}
		if(grid[target.data('x')][target.data('y')]!==CELL_CLEAR){
			if(!target.hasClass('flag') && mineCountSign>0){
				target.addClass('flag');
				mineCountSign--;
			} else if(target.hasClass('flag')){
				target.removeClass('flag');
				mineCountSign++;
			}
			mineCountObj.text(mineCountSign);
			drawGameHelper();
		}
	}
	
	//产生地雷
	function randomMine(randomCount){
		if(!randomCount){
			randomCount = 0;
		}
		var x = Math.round(Math.random()*(mineSize.x-1));
		var y = Math.round(Math.random()*(mineSize.y-1));
		if(grid[x][y]===CELL_EMPTY){
			randomCount++;
			grid[x][y] = CELL_MINE;
			if(randomCount < mineCount ){
				randomMine(randomCount);
			}
		} else {
			randomMine(randomCount);
		}
	}
	
	/** 扫雷主方法，以扫出的空白位置为基点，搜索周围的所有的个格子的地雷总数，并显示出来 */
	function mineClearanceEvent(event){
		// 过滤点击事件在 table 边框被触发的清苦，只保留从 TD 标签触发的事件处理逻辑
		if(event.target.id.indexOf('box_')>-1){
			var obj = $(event.target);
			var x = obj.data('x');
			var y = obj.data('y');

			// 只有在游戏开始的状态下，以及被点击的格式没有被标记为地雷的时候，此格子才能被点击，被触发扫雷的逻辑
			if(gameStatus===GAME_OFF || obj.hasClass('flag') || grid[x][y]===CELL_CLEAR){
				drawHelpLine(event);
				return;
			}
			countLabel.text(parseInt(countLabel.text())+1);
			if(grid[x][y]===CELL_EMPTY){
				doMineClearance(x, y , obj);
				drawGameHelper();
				drawHelpLine(event);
				//判断是否扫除所有的地雷，是则表示游戏胜利
				var unClick = mineSize.count - mineMap.find('td.onbump').length;
				if( unClick === mineCount ){
					gameWin();
				}
			} else if(grid[x][y]===CELL_MINE){
				// 游戏失败
				gameOver(obj);
			}
		}
	}
	/** 执行扫雷的游戏逻辑 */
	function doMineClearance(x, y, obj){
		if(obj.hasClass('flag')){
			return;
		}
		grid[x][y] = CELL_CLEAR;
		// {mineCount:0, emptyCell:[]}
		var mineObj =  hasMines([
			{x:x-1, y:y-1},
			{x:x-1, y:y},
			{x:x-1, y:y+1},
			{x:x+1, y:y-1},
			{x:x+1, y:y},
			{x:x+1, y:y+1},
			{x:x, y:y-1},
			{x:x, y:y+1}
		]);

		// 标记附近的地雷总数
		if( mineObj.mineCount >0 ){
			obj.text('').removeClass('rateTxt');
			obj.html(mineObj.mineCount);
			obj.addClass('on' + mineObj.mineCount + ' onbump');
		} else {
			obj.addClass('onbump');
			// 遇到地雷总数为零的情况，对付经的单元格进行自动排雷
			$(mineObj.emptyCell).each(function(){
				doMineClearance(this.x, this.y, this.obj);
			});
		}
	}
	
	/** 统计清扫的格子周围多少颗地雷 */
	function hasMines(dataArr){
		var minesObj = {mineCount:0, emptyCell:[]};
		$(dataArr).each(function(){
			if(this.x>=0 && this.x<mineSize.x && this.y>=0 && this.y<mineSize.y){
				if(grid[this.x][this.y]===CELL_EMPTY) {
					minesObj.emptyCell.push( {x:this.x, y:this.y, obj:$('#box_' + this.x + '_' + this.y)} );
				} else if(grid[this.x][this.y]===CELL_MINE){
					minesObj.mineCount = minesObj.mineCount + 1;
				}
			}
		});
		return minesObj;
	}
	/** 游戏失败 */
	function gameOver(obj){
		gameStatus = GAME_OFF;
		statusBtn.attr('src','image/cry.png');
		obj.addClass('boom');
		showAllMine();
		alert('很遗憾，你踩到地雷了！');
	}
	/** 游戏胜利 */
	function gameWin(){
		gameStatus = GAME_OFF;
		statusBtn.attr('src','image/happy.png');
		showAllMine();
		alert('恭喜你清空了所有的地雷！');
	}
	/** 游戏结束后，显示所有的地雷 */
	function showAllMine(){
		for(var i=0; i<mineSize.x; i++){
			for(var j=0; j<mineSize.y; j++){
				if(grid[i][j]===CELL_MINE){
					$('#box_' + i + '_' + j).addClass('diLei');
				}
			}
		}
	}
	
	/** 绘制游戏帮助器，帮助计算出现地雷的概率 */
	function drawGameHelper(){
		if(helpSwitch.filter(':checked').length){
			gamePage.find('.rateTxt').text('').removeClass('rateTxt');
			gamePage.find('table td.onbump').each(function(){
				var mineCount = parseInt(this.textContent);
				var x = parseInt(this.dataset['x']);
				var y = parseInt(this.dataset['y']);
				drawRate(mineCount, [
					{x:x-1, y:y-1},
					{x:x-1, y:y},
					{x:x-1, y:y+1},
					{x:x+1, y:y-1},
					{x:x+1, y:y},
					{x:x+1, y:y+1},
					{x:x, y:y-1},
					{x:x, y:y+1}
					]);
			});
		}
	}
	/** 计算附近单元格出现地雷的概率，并将概率显示在帮助器里面 */
	function drawRate(mineCount, dataArr){
		var emptyCount = 0;
		var cellTemp;
		$(dataArr).each(function(){
			if(this.x>=0 && this.x<mineSize.x && this.y>=0 && this.y<mineSize.y){
				cellTemp = gamePage.find('#box_' + this.x + '_' + this.y);
				if(!cellTemp.hasClass('onbump')){
					if(cellTemp.hasClass('flag')) {
						mineCount--;
					} else {
						emptyCount++;
					}
				}
			}
		});
		if(emptyCount>0){
			var rate = Math.round(mineCount * 100 / emptyCount) / 100;
			var rate_temp;
			$(dataArr).each(function(){
				if(this.x>=0 && this.x<mineSize.x && this.y>=0 && this.y<mineSize.y){
					cellTemp = gamePage.find('#box_' + this.x + '_' + this.y);
					if(!cellTemp.hasClass('onbump')){
						rate_temp = 0;
						if(cellTemp.text()){
							rate_temp = parseFloat(cellTemp.text());
						}
						if(!cellTemp.hasClass('flag') && !cellTemp.hasClass('flag')) {
							cellTemp.text(Math.round((rate + rate_temp) * 100) / 100).addClass('rateTxt');
						} 
					}
				}
			});
		}
	}
	
	/** 辅助线 */
	function drawHelpLine(event){
		var target = event.target;
		if($(target).hasClass('onbump') && lineHelper.filter(':checked').length){
			$('.helpline').removeClass('helpline');
			var mineCount = parseInt(target.textContent);
			var x = parseInt(target.dataset['x']);
			var y = parseInt(target.dataset['y']);
			$(target).addClass('helpline');
			$([
				{x:x-1, y:y-1}, {x:x-1, y:y}, {x:x-1, y:y+1}, {x:x+1, y:y-1}, {x:x+1, y:y}, {x:x+1, y:y+1}, {x:x, y:y-1}, {x:x, y:y+1}
				]).each(function(){
					if(this.x>=0 && this.x<mineSize.x && this.y>=0 && this.y<mineSize.y){
						mineMap.find('#box_' + this.x + '_' + this.y).addClass('helpline');
					}
				});
		}
	}
	// 初始化 计时 和 总步数统计 的数据，并启动计时器
	function timeCounting(){
		countLabel.text(0);
		timeLabel.text('00:00');
		startTime = Date.now();
		var timeGap;
		var timeInterval = setInterval(function() {
			timeGap = Math.round((Date.now() - startTime) / 1000);
			var temp = Math.round(timeGap/60);
			var str = temp>9?temp:('0' + temp);
			temp = timeGap%60;
			str = str + ':' + (temp>9?temp:('0' + temp));
			timeLabel.text(str);
			if(gameStatus===GAME_OFF){
				// clear 方法一定要定时器函数内部调用才有效果
				clearInterval(timeInterval);
			}
		}, 1000);
	}
	
	/**
	 * 在已标记完所有的地雷后，自动清空周围的格子
	 * @param {event} JQuery 事件对象
	 */
	function autoClear(event){
		var target = event.target;
		if($(target).hasClass('onbump') && gameStatus===GAME_ON && target.textContent){
			var mineNum = parseInt(target.textContent);
			var x = parseInt(target.dataset['x']);
			var y = parseInt(target.dataset['y']);
			var emptyCell = [];
			var flagCount = 0;
			var cellTemp;
			$([
				{x:x-1, y:y-1}, {x:x-1, y:y}, {x:x-1, y:y+1}, {x:x+1, y:y-1}, {x:x+1, y:y}, {x:x+1, y:y+1}, {x:x, y:y-1}, {x:x, y:y+1}
			   ]).each(function(){
					if(this.x>=0 && this.x<mineSize.x && this.y>=0 && this.y<mineSize.y){
						cellTemp = mineMap.find('#box_' + this.x + '_' + this.y);
						if(cellTemp.hasClass('flag')){
							flagCount ++;
						} else if(!cellTemp.hasClass('onbump')){
							emptyCell.push({x:this.x, y:this.y, dom:cellTemp});
						}
					}
			});
			if(flagCount===mineNum){
				countLabel.text(parseInt(countLabel.text())+1);
				$(emptyCell).each(function(){
					if(grid[this.x][this.y]===CELL_EMPTY){
						doMineClearance(this.x, this.y , this.dom);
						//判断是否扫除所有的地雷，是则表示游戏胜利
						var unClick = mineSize.count - mineMap.find('td.onbump').length;
						if( unClick === mineCount ){
							gameWin();
						}
					} else if(grid[this.x][this.y]===CELL_MINE){
						// 游戏失败
						gameOver(this.dom);
					}
					
				});
				drawGameHelper();
			}
		}
	}
	
	function startGame(){
		gameStatus = GAME_OFF;
		createMap(levelRadio.filter(':checked')[0]);
	}

	window.setTimeout(function(){
		$('#loadingPage').hide();
		gamePage.removeClass('hide');
		$('.game-statistics').removeClass('hide');
	}, 2000);
	
	//屏蔽右键菜单
	gamePage[0].oncontextmenu = function() {
		event.returnValue = false;	//geogle
		return false;	//IE
	}

	// 设置开始游戏的事件
	statusBtn.click(startGame);
	// 调用开始游戏的事件
	startGame();
	// 切换游戏等级后，需要重新开始游戏
	levelRadio.change(startGame);
	$('#gameStartBtn').click(startGame);
	// 扫雷的事件
	mineMap.click(mineClearanceEvent);
	mineMap.dblclick(autoClear);
	
	
	helpSwitch.change(function(){
		if(this.checked){
			drawGameHelper();
		} else {
			gamePage.find('.rateTxt').text('').removeClass('rateTxt');
		}
	});
	lineHelper.change(function(){
		if(!this.checked){
			$('.helpline').removeClass('helpline');
		}
	});
	$('input[name=gameSize]').change(function(){
		if(this.checked){
			mineMap.removeClass('small middle large').addClass(this.value);
		}
	});
});